/* Copyright 2009 Requirements Management System 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.remas.preview;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.validator.GenericValidator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorInput;
import org.mags.remas.control.DocumentInput;
import org.mags.remas.control.commons.IStartClass;
import org.mags.remas.logic.EntityFileUtils;
import org.mags.remas.model.entity.EntityFile;
import org.mags.remas.server.EmbeddedServer;
import org.mags.remas.server.ImageUtils;
import org.mags.remas.view.commons.ImageProvider;
import org.mags.remas.view.commons.RelationshipEditorBase;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
import org.xhtmlrenderer.pdf.ITextRenderer;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class HtmlView extends RelationshipEditorBase {
	public static final String ID = "org.mags.remas.preview.htmlView";
	private DocumentInput input;
	private Browser browser;
	private String urlPrefix = "http://";
	private final String PDF_TYPE = "pdf";
	private final String HTML_TYPE = "html";
	private final String ODF_TYPE = "odf";
	
	@Override
	public void init(IEditorInput input) {
		this.input = (DocumentInput)input;		
	}	
	public void process() {
		Map<String, Object> context = new HashMap<String, Object>();
		context.put("entityRelationship", entityRelationship);				
		IStartClass process;
		try {
			process = (IStartClass)Class.forName(entityRelationship.getEntity().getEntityType().getProcessClass()).newInstance();
		} catch (Exception e) {
			if(e instanceof RuntimeException)
				throw (RuntimeException)e;
			else
				throw new RuntimeException(e);
		}
		process.execute(context);		
		refresh();
	}
	public void refresh() {
		browser.refresh();
	}
	public void print() {
		//TODO: TEMPORAL
		browser.execute("window.print();");
		/*
		PrintDialog printDialog = new PrintDialog(getSite().getShell());
		PrinterData printerData = printDialog.open();
		if (printerData != null) {
			Printer printer = new Printer(printerData);
			GC gc = new GC(printer);
			if (!printer.startJob("Test"))
				System.out.println("Testing");
			else {
				if (!printer.startPage())
					System.out.println("Error");
				else {
					browser.print(gc);
					printer.endPage();
				}
			printer.endJob();
			}
			gc.dispose();
			printer.dispose();
		}
		*/
	}
	public void exportHTML(File file) {
		FileOutputStream stream=null;
		ByteArrayInputStream _stream= null;
		try {
			List<EntityFile> files = EntityFileUtils.getFiles(input.getEntityRelationship().getEntity().getEntityId());
			if(files.size()>0) {
				byte[] data = files.get(0).getRawContent();
				stream = new FileOutputStream(file);
				stream.write(data);
				Tidy tidy = new Tidy();
				tidy.setQuiet(true);
				tidy.setShowWarnings(false);
				tidy.setForceOutput(true);
				_stream = new ByteArrayInputStream(data);
				Document document = tidy.parseDOM(_stream, null);
				stream.close();
				String directory = file.getParentFile().getPath();
				if(!directory.endsWith(File.separator))
					directory = directory + File.separator;
				NodeList nodeList = document.getElementsByTagName("img");
				for(int i=0;i<=nodeList.getLength()-1;i++) {
					Node node = nodeList.item(i);
					NamedNodeMap attributes = node.getAttributes();
					Node _src = attributes.getNamedItem("src");
					String src = _src.getNodeValue();
					int index = src.lastIndexOf("/");
					if(index>1) {
						String path = src.substring(src.indexOf("/"));
						StringBuffer contentType = new StringBuffer();
						String subDir = directory+src.substring(0, index+1).replace("/", File.separator);
						String _file = src.substring(index+1);
						File folder = new File(subDir);
						if(folder.exists()&&!folder.isDirectory())
							throw new RuntimeException("folder images can't be created");
						else if(!folder.exists()) {
							if(!folder.mkdirs())
								throw new RuntimeException("folder images can't be created");
						}
						byte[] image = ImageUtils.getImageByPath(path, contentType);
						File imageFile = new File(subDir+_file);
						stream = new FileOutputStream(imageFile);
						stream.write(image);						
						stream.close();
					}
				}
			}
		} catch (Exception e) {
			if(e instanceof RuntimeException)
				throw (RuntimeException)e;
			else
				throw new RuntimeException(e);
		} finally {
			try {
				if(stream!=null)
					stream.close();
				if(_stream!=null)
					_stream.close();
			} catch (Exception e) {/*IGNORE EXCEPTION*/}
		}		
	}
	public void exportODF(File file) {
		//ALGORITMO PARA EXPORTAR A ODF
	}
	public void exportPDF(File file) {
		FileOutputStream stream=null;
		try {
			ITextRenderer renderer = new ITextRenderer();
			renderer.setDocument(urlPrefix+"document?documentId="+input.getEntityRelationship().getEntityRelationshipId());
		    stream = new FileOutputStream(file.getPath());
		    renderer.layout();
		    renderer.createPDF(stream);
		} catch (Exception e) {
			if(e instanceof RuntimeException)
				throw (RuntimeException)e;
			else
				throw new RuntimeException(e);
		} finally {
			try {
				if(stream!=null)
					stream.close();
			} catch(Exception _e){/*IGNORE EXCEPTION*/}
		}
	}
	public void export(String type) {
		FileDialog dialog = new FileDialog(super.getSite().getShell(), SWT.SAVE);
		dialog.setText("Save As");
		String[] filterExt = {"*."+type};
		dialog.setFilterExtensions(filterExt);
		String selected = dialog.open();
		if(!GenericValidator.isBlankOrNull(selected)) {
			File file = new File(selected);
			if(file.exists()) {
				if(MessageDialog.openQuestion(super.getSite().getShell(), "The file exists", "Do you want rewrite the file?"))
					file.delete();
				else
					return;
			} 
			if(PDF_TYPE.equals(type))
				exportPDF(file);
			else if(HTML_TYPE.equals(type))
				exportHTML(file);
			else if(ODF_TYPE.equals(type))
				exportODF(file);			
		}
	}
	protected void createBrowser(Composite parent) {
		GridData browserGridData = new GridData();
		browserGridData.horizontalAlignment = SWT.FILL;
		browserGridData.grabExcessHorizontalSpace = true;
		browserGridData.verticalAlignment = SWT.FILL;	
		browserGridData.grabExcessVerticalSpace=true;			
		browser = new Browser(parent, SWT.BORDER);
		browser.setLayoutData(browserGridData);
		browser.setJavascriptEnabled(true);
		browser.setUrl(urlPrefix+"document?documentId="+entityRelationship.getEntityRelationshipId());		
	}
	protected void createToolBar(Composite parent) {
		ToolBar toolBar = new ToolBar(parent, SWT.FLAT);
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.RIGHT;
		gridData.grabExcessHorizontalSpace = true;		
		toolBar.setLayoutData(gridData);
		
		ToolItem refreshButton = new ToolItem(toolBar, SWT.NONE);		
		refreshButton.setText("refresh");
		refreshButton.setImage(ImageProvider.getCommonImage("refresh.png"));
		refreshButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					refresh();
				} catch(Exception ex) {
					exceptionCatched(ex);
				}
			}
		});

		if(!GenericValidator.isBlankOrNull(input.getEntityRelationship().getEntity().getEntityType().getProcessClass())) {
			ToolItem processButton = new ToolItem(toolBar, SWT.NONE);		
			processButton.setText("process");
			processButton.setImage(ImageProvider.getCommonImage("process.png"));
			processButton.addSelectionListener(new SelectionListener() {
				public void widgetDefaultSelected(SelectionEvent e) {
				}
				public void widgetSelected(SelectionEvent e) {
					try {
						process();
					} catch(Exception ex) {
						exceptionCatched(ex);
					}
				}
			});			
		}
		
		ToolItem printButton = new ToolItem(toolBar, SWT.NONE);
		printButton.setText("print");
		printButton.setImage(ImageProvider.getCommonImage("print.png"));
		printButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					print();
				} catch(Exception ex) {
					exceptionCatched(ex);
				}
			}
		});
		
		ToolItem pdfButton = new ToolItem(toolBar, SWT.NONE);
		pdfButton.setText("pdf");
		pdfButton.setImage(ImageProvider.getCommonImage("pdf.png"));
		pdfButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					export(PDF_TYPE);
				} catch(Exception ex) {
					exceptionCatched(ex);
				}
			}
		});

		ToolItem htmlButton = new ToolItem(toolBar, SWT.NONE);
		htmlButton.setText("html");
		htmlButton.setImage(ImageProvider.getCommonImage("html.png"));
		htmlButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					export(HTML_TYPE);
				} catch(Exception ex) {
					exceptionCatched(ex);
				}
			}
		});
		
		/*
		ToolItem odfButton = new ToolItem(toolBar, SWT.NONE);
		odfButton.setText("odf");
		odfButton.setImage(ImageProvider.getCommonImage("odf.png"));
		odfButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					export(ODF_TYPE);
				} catch(Exception ex) {
					exceptionCatched(ex);
				}
			}
		});
		*/		
	}
	public void createPartControl(Composite parent) {
		try {
			EmbeddedServer.getInstance().start();
			urlPrefix = urlPrefix + EmbeddedServer.getInstance().getHost()
			+ ":" + EmbeddedServer.getInstance().getPort() + "/" + EmbeddedServer.DEFAULT_WEBAPP_NAME + "/";
		} catch(Exception e) {
			exceptionCatched(e);
		}		
		GridLayout gridLayout = new GridLayout(1, true);
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		gridLayout.verticalSpacing = 0;
		gridLayout.horizontalSpacing = 0;		
		parent.setLayout(gridLayout);
		createToolBar(parent);
		createBrowser(parent);		
	}
	public void setFocus() {
		browser.setFocus();
	}
	@Override
	public boolean ignoreException(Exception e) {
		return false;
	}
}
